/*
 * Copyright (c) 2003-2010, Live Media Pty. Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *     conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *  3. Neither the name of Live Media nor the names of its contributors may be used to endorse
 *     or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.colony.networkvm;

import com.argot.TypeException;
import com.argot.TypeLibrary;
import com.argot.TypeMap;
import com.argot.TypeMapperCore;
import com.argot.TypeMapperDynamic;
import com.argot.TypeMapperError;
import com.argot.network.TypeServer;
import com.argot.remote.MetaLocation;
import com.argot.remote.MetaObject;
import com.colony.ColonyEnvironment;
import com.colony.ColonyException;
import com.colony.IColonyServer;
import com.colony.IContainer;
import com.colony.channel.ChannelLoader;
import com.colony.channel.ChannelServer;
import com.colony.remote.RemoteException;
import com.colony.remote.rpc.RpcDelegateFactory;
import com.colony.remote.rpc.RpcMetaServer;
import com.colony.remote.rpc.RpcMetaSkeleton;
import com.colony.transport.Server;

public class NvmServer
implements IColonyServer
{
	private boolean _isBound;
	
	private ColonyEnvironment _environment;
	private TypeLibrary _library;
	private IContainer _container;
	private NvmDelegateFactory _delegateFactory;
	private MetaLocation _hostLocation;
	private Server _link;
	private Server _channel;
	
	public NvmServer( MetaLocation hostLocation, Server link, Server channel )
	{
		_link = link;
		_channel = channel;
		_hostLocation = hostLocation;
		_delegateFactory = new NvmDelegateFactory();
	}
	
	public ColonyEnvironment getEnvironment()
	{
		return _environment;
	}

	public void bind( ColonyEnvironment environment ) 
	throws ColonyException, RemoteException, TypeException
	{
		if ( _isBound ) throw new RemoteException("Server already bound to environment");
		_isBound = true;

		_environment = environment;
		_container = environment.getHostContainer();
		_library = environment.getTypeLibrary();
		
		//DynamicTypeMap dynMap = new DynamicTypeMap( _library );
		//TypeMapCore.mapMeta( dynMap, _library );
		//dynMap.map( 42, _library.getStreamId("dictionary.words"));		
		TypeMap dynMap = new TypeMap( _library, new TypeMapperDynamic( new TypeMapperCore( new TypeMapperError())));
		dynMap.setReference(TypeMap.REFERENCE_MAP, dynMap);
		
		NvmEnvironment nvmEnvironment = new NvmEnvironment(_environment, _delegateFactory, _library);
		NvmHostServer nvmHost = new NvmHostServer( nvmEnvironment, dynMap );
		_container.addObject( _hostLocation, INvmHost.TYPENAME, nvmHost );

		RpcDelegateFactory delegateFactory = new RpcDelegateFactory();
		delegateFactory.setBackDelegate( NvmHostServer.class, new RpcMetaSkeleton());
		RpcMetaServer rpcHost = new RpcMetaServer( delegateFactory, _container, dynMap);
		TypeServer typeServer = new TypeServer( _library, dynMap, rpcHost );			
		typeServer.setBaseObject( new MetaObject( _hostLocation, _library.getTypeId(INvmHost.TYPENAME)));
		_link.setTypeLink(typeServer);

		if ( _channel != null )
		{
			ChannelServer channelServer = new ChannelServer( _library, _channel.getPool() );
			_channel.setTypeLink(channelServer.getBack());
			ChannelLoader.bindServerMap(dynMap, channelServer );
		}

	}

	public boolean isBound()
	{
		return _isBound;
	}
	
}
